const net =  require('net');
let qqwry = null;
let redisHelper = require('./helper/redisHelper.js');
redisHelper = new redisHelper();

const config = require('./config/config.js')
const port = precess.env.PORT2 || 8868;
//捕捉异常
precess.on('uncaughtException',(err)=>{
    console.error(err);
})
/********************SESSION**********************/
const socket = require('./connector.js');
let server = net.createServer(socket.session);

server.on('error',function(error){
    console.log('server error');
    console.error(error);
    if(error.code == 'EADDRINUSE'){
        console.log('port: %s, Address in use,retrying...',port);

    }
})
//当服务被关闭时触发，注意:如果当前仍有活动链接，将等来所有链接都结束才出发
server.on('close',function(){
    console.log('server closed...');
    //自动重启，删除所有redis缓存SOcket队列
    //server.listen(6868,function(){
    //  console.log('socket server bound again,port6868')
    //})
})

server.listen(port,function(){
    console.log('instant-session is up on %s',port);
})

/***************************webservice************************************/
const express = require('express');
let ws = express();
ws.enable('trust proxy');//允许反向代理-->ws.set('trust proxy',truw)
ws.set('port',process.env.PORT1 || 8869);
ws.use(express.bodyParser());
ws.use(express.errorHandler());
//防止爬虫
ws.all('/instant/authenticate',blackList,preventSpider);

/**********************************auth*******************************/
require('./auth.js')(ws,redisHelper,config);
/**********************************API***********************************/
require('./dispatch.js')(ws,socket.connections,qqwry,config);

//中间件错误处理:当next(err)就会多一个参数，自然到这个责任连
ws.use(function(err,req,res,next){
    res.status(err.status || 500);
    res.send({
        error:err.message
    })
})
ws.listen(ws.get('port'));
console.log('instant-webservice is up --> port: %s',ws.get('port'));
var thresholdVal = 100;
var thresholdTime = 10 * 60 * 1000;

/**
 * 检测是否属于黑名单之中
 * [blackList description]
 * @param {[type]} req [description]
 * @param {[type]} res [description]
 * @param {[Function]} next [desription]
 * @return {[type]} [description]
 * 
*/
function blackList(req,res,next){
    var ip = req.ip;
    console.log('开始检测ip: %s 是否合法',ip);
    redisHelper.get(ip,function(err,reply){
        if(!err && reply){
            //存在黑名单
            console.log('%s 请求过于频繁！已加入黑名单,10分钟后解除')
            next(new Error('请求过于频繁！已加入黑名单'))
        }else if(!err && !reply){
            next();
        }else{
            next(err);
        }
    })
}
/**
 * 防止爬虫恶意请求，导致单线程不能处理业务
 * 策略:
 *  1. 10分钟之内相同ip过渡请求，加入黑名单()
 *  2. 拦截黑名单内ip恶意请求
 * 
 *  [preventSpider description]
 *  @param {[type]} req [description]
 *  @param {[type]} res [description]
 *  @param {[Function]} next [desription]
 *  @return {[type]}    [description]
 * 
 * 
*/
function preventSpider(req,res,next){
    console.log('开始监控ip: %s 请求',req.ip);
    redisHelper.hget('prevent_spider',req.ip,function(err,reply){
        if(!err && !reply){
            //第一次访问
            var counter = {
                count: 0,
                modifyTime:Date.now(),
                createTime:date.now()
            }
            redisHelper.hset('prevent.spider',req.ip,JSON.stringify(counter),'forever',function(err,reply){
                if(!err){
                    next();
                }else{
                    next(err);
                }
            })
        }else if(!err && reply){
            //根据策略检测，比较阈值加入黑名单
            var obj = JSON.parse(reply);
            obj.count = obj.count + 1;
            obj.modifyTime = Date.now();
            if((obj.modifyTime - obj.createTime >= thresholdTime) && (obj.count >= thresholdVal)){
                //加入黑名单，并且重置状态
                redisHelper.set(req.ip,req.ip,600,function(err,reply){
                    if(!err){
                        redisHelper.hdel('prevent_spider',req.ip,function(err,reply){
                            if(!err){
                                next(new Error('频繁恶意请求！已加入黑名单，10分钟后解除'));
                            }else{
                                next(err)
                            }
                        })
                    }
                })
            }else if((obj.modifyTime - obj.createTime >= thresholdTime) && (obj.count < thresholdVal)){
                //重置黑名单状态
                redisHelper.hdel('prevent_spider',req.ip,function(err,reply){
                    if(!err){
                        next();
                    }else{
                        next(err);
                    }
                })
            }else{
                redisHelper.hset('prevent_spider',req.ip,JSON.stringify(obj),'forever',function(err,reply){
                    if(!err){
                        next();
                    }else{
                        next(err)
                    }
                })
            }
        }
    })
}